package com.zl.tby.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zl.tby.core.base.bean.TbyPageResult;
import com.zl.tby.core.base.enums.TbyEducationViewCategoryEnum;
import com.zl.tby.core.base.util.HttpUtil;
import com.zl.tby.core.base.util.NetworkImageThumbnailGenerator;
import com.zl.tby.core.base.util.ToolsUtil;
import com.zl.tby.core.base.util.VideoToImageUtil;
import com.zl.tby.core.common.FileResult;
import com.zl.tby.core.common.R;
import com.zl.tby.dto.TbyEducationViewQuery;
import com.zl.tby.model.*;
import com.zl.tby.repository.TbyAnimalPlantRepo;
import com.zl.tby.repository.TbyEducationRoomRepo;
import com.zl.tby.repository.TbyEducationSquareRepo;
import com.zl.tby.repository.TbyEducationViewRepo;
import com.zl.tby.screen.vo.education.TbyEducationResourceScreenBean;
import com.zl.tby.service.ITbyEducationRoomService;
import com.zl.tby.service.ITbyEducationViewService;
import com.zl.tby.service.ITbySpeciesCategoryService;
import com.zl.tby.vo.TbyEducationViewForm;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Tran;
import org.noear.wood.DbContext;
import org.noear.wood.DbTableQuery;
import org.noear.wood.annotation.Db;
import org.noear.wood.impl.IPageImpl;
import org.noear.wood.utils.StringUtils;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 视图管理
 * @author changpeng
 * @version 1.0
 * @since 2024/8/6 20:22
 */
@Slf4j
@Component
public class TbyEducationViewServiceImpl implements ITbyEducationViewService {

    @Db
    private TbyEducationViewRepo tbyEducationViewRepo;
    @Db
    private TbyAnimalPlantRepo tbyAnimalPlantRepo;
    @Db
    private TbyEducationRoomRepo tbyEducationRoomRepo;
    @Db
    private TbyEducationSquareRepo tbyEducationSquareRepo;
    @Inject
    private ITbySpeciesCategoryService tbySpeciesCategoryService;
    @Db
    private DbContext db;
    @Inject
    private ITbyEducationRoomService tbyEducationRoomService;
    @Inject("${server.request.upload-url}")
    private String uploadUrl;
    @Inject("${server.request.system-url}")
    private String systemUrl;
    @Inject("${server.request.temp-url}")
    private String tempUrl;


    @Override
    @Tran
    public R<TbyEducationView> add(TbyEducationViewForm form) {
        TbyEducationView entity = form.createEntity();
        entity.setCreateBy(ToolsUtil.getLoginUserId());
        entity.setCreateTime(LocalDateTime.now());
        long id = tbyEducationViewRepo.insert(entity, true);
        entity.setId(id);
        return R.ok(entity);
    }

    @Override
    @Tran
    public R<TbyEducationView> update(TbyEducationViewForm form) {
        TbyEducationView entity = this.get(form.getId());
        if (entity == null) {
            return R.failed("数据不存在");
        }
        form.updateEntity(entity);
        entity.setUpdateBy(ToolsUtil.getLoginUserId());
        entity.setUpdateTime(LocalDateTime.now());
        tbyEducationViewRepo.updateById(entity, false);
        return R.ok(entity);
    }

    @Override
    public int delete(Long id) {
        TbyEducationView db = this.get(id);
        int rs = tbyEducationViewRepo.deleteById(id);
        if (db != null && db.getCategory().equals(TbyEducationViewCategoryEnum.XJG.toString())) {
            // 宣教馆更新
            tbyEducationRoomService.updateImageAndVideoCount();
        }
        return rs;
    }

    @Override
    public TbyEducationView get(Long id) {
        return tbyEducationViewRepo.selectById(id);
    }

    @Override
    public TbyPageResult<TbyEducationViewForm> page(TbyEducationViewQuery query) {
        try {
            List<Long> typeLevelIdList = null;
            TbyEducationViewCategoryEnum categoryEnum = TbyEducationViewCategoryEnum.getByCode(query.getCategory());
            if (categoryEnum.toString().equals(TbyEducationViewCategoryEnum.WZ.toString())) {
                // 物种的情况，拼装物种分类的条件
                if (query.getTypeLevel() != null && query.getBusinessId() == null) {
                    TbySpeciesCategory category = this.tbySpeciesCategoryService.get(query.getTypeLevel());
                    if (category != null) {
                        typeLevelIdList = new ArrayList<>();
                        typeLevelIdList.add(category.getId());
                        ToolsUtil.whileFindId(this.tbySpeciesCategoryService.list(), category.getId(), typeLevelIdList);
                    }
                }
            }
            DbTableQuery tableQuery = createQuery(query, categoryEnum, typeLevelIdList);
            List<TbyEducationViewForm> dataList = tableQuery.selectList(column(categoryEnum), TbyEducationViewForm.class);
            dataList.forEach(item -> {
                item.fillExtendProp();
            });
            long total = tableQuery.selectCount();
            return new TbyPageResult(new IPageImpl(dataList, total, query.getSize()), query);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return new TbyPageResult(new IPageImpl(new ArrayList(), 0, query.getSize()), query);
    }

    @Override
    public List<TbyEducationViewForm> list(TbyEducationViewQuery query) {
        List<TbyEducationViewForm> dataList = new ArrayList<>();
        try {
            TbyEducationViewCategoryEnum categoryEnum = TbyEducationViewCategoryEnum.getByCode(query.getCategory());
            dataList = createQuery(query, categoryEnum, null).selectList(column(categoryEnum), TbyEducationViewForm.class);
            dataList.forEach(item -> {
                item.fillExtendProp();
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return dataList;
    }

    private DbTableQuery createQuery(TbyEducationViewQuery query, TbyEducationViewCategoryEnum categoryEnum, List<Long> typeLevelIdList) throws Exception {
        DbTableQuery tableQuery = db.table("tby_education_view v");
        tableQuery.innerJoin(categoryEnum.getTableName())
                .onEq("v.business_id", categoryEnum.getColumn()).whereTrue()
                .andIf(StringUtils.isNotEmpty(query.getCategory()), "v.category = ?", query.getCategory())
                .andIf(StringUtils.isNotEmpty(query.getType()), "v.type = ?", query.getType())
                .andIf(StringUtils.isNotEmpty(query.getCreateTimeBegin()), "v.create_time >= ?", query.getCreateTimeBegin())
                .andIf(StringUtils.isNotEmpty(query.getCreateTimeEnd()), "v.create_time <= ?", query.getCreateTimeEnd())
                .andIf(query.getBusinessId() != null, "v.business_id = ?", query.getBusinessId());
        if (typeLevelIdList != null && typeLevelIdList.size() > 0 && categoryEnum.toString().equals(TbyEducationViewCategoryEnum.WZ.toString()) && query.getBusinessId() == null) {
            // 物种的情况， 选择了物种分类，并且没有选择物种， 按照物种分类查询
            tableQuery.andIn("ap.type_level", typeLevelIdList);
        }
        tableQuery.limit(query.getOffset(), query.getSize());
        if (StringUtils.isNotEmpty(query.getOrder())) {
            tableQuery.orderBy(query.getOrder());
        }
        return tableQuery;
    }

    private String column(TbyEducationViewCategoryEnum categoryEnum) {
        String showColumn = "v.*, ap.ch_name as business_name";
        if (categoryEnum == TbyEducationViewCategoryEnum.XJG) {
            showColumn = "v.*, room.name as business_name";
        }
        return showColumn;
    }

    @Override
    public R<Void> saveBatch(String formData) {
        try {
            if (StringUtils.isEmpty(formData)) {
                return R.failed("请上传附件");
            }
            List<TbyEducationView> entityList = new ObjectMapper().readValue(formData, new TypeReference<List<TbyEducationView>>() {});
            boolean isXjq = false;
            if (entityList.size() > 0) {
                if (entityList.get(0).getCategory().equals(TbyEducationViewCategoryEnum.XJG.toString())) {
                    isXjq = true;
                }
            }
            entityList.forEach(item -> {
                item.setId(null);
                item.setDeleteFlag(0);
                item.setCreateBy(ToolsUtil.getLoginUserId());
                item.setCreateTime(LocalDateTime.now());

            });
            this.tbyEducationViewRepo.insertList(entityList);
            if (isXjq) {
                tbyEducationRoomService.updateImageAndVideoCount();
            }
            return R.ok();
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }

    @Override
    public R<Void> updateBusinessId(String ids, Long businessId) {
        if (StringUtils.isEmpty(ids) || businessId == null || businessId.compareTo(0L) == 0) {
            return R.failed("参数缺失");
        }
        String[] array = ToolsUtil.splitStr(ids, ',');
        for (String s : array) {
            TbyEducationView entity = new TbyEducationView();
            entity.setId(Long.parseLong(s));
            entity.setBusinessId(businessId);
            entity.setUpdateBy(ToolsUtil.getLoginUserId());
            entity.setUpdateTime(LocalDateTime.now());
            tbyEducationViewRepo.updateById(entity, true);
        }
        TbyEducationView db = this.get(businessId);
        if (db != null && db.getCategory().equals(TbyEducationViewCategoryEnum.XJG.toString())) {
            // 宣教馆更新
            tbyEducationRoomService.updateImageAndVideoCount();
        }
        return R.ok();
    }

    @Override
    public TbyEducationResourceScreenBean educationSteleAndView(String category, Long businessId) {
        TbyEducationResourceScreenBean result = new TbyEducationResourceScreenBean();
        if (category.equals(TbyEducationViewCategoryEnum.WZ.toString())) {
            TbyAnimalPlant entity = this.tbyAnimalPlantRepo.selectById(businessId);
            if (entity != null) {
                result.setViewBusinessId(entity.getId());
                result.setViewBusinessName(entity.getChName());
                result.setViewBusinessContent(entity.getRemark());
            }
        } else if (category.equals(TbyEducationViewCategoryEnum.SQUARE.toString())) {
            TbyEducationSquare entity = this.tbyEducationSquareRepo.selectById(businessId);
            if (entity != null) {
                result.setViewBusinessId(entity.getId());
                result.setViewBusinessName(entity.getName());
                result.setViewBusinessContent(entity.getContent());
            }
        } else {
            TbyEducationRoom entity = this.tbyEducationRoomRepo.selectById(businessId);
            if (entity != null) {
                result.setViewBusinessId(entity.getId());
                result.setViewBusinessName(entity.getName());
                result.setViewBusinessContent(entity.getContent());
            }
        }
        List<TbyEducationView> viewList = this.tbyEducationViewRepo.selectList(mp -> {
            mp.whereTrue().andEq("category", category).andEq("business_id", businessId);
        });
        result.fillViewInformation(viewList);
        return result;
    }

    @Override
    public void createThumbnail(Long id) {
        if (id != null) {
            TbyEducationView view = get(id);
            create(view);
            return;
        }
        try {
            List<TbyEducationView> dataList = db.table("tby_education_view v").whereTrue()
                    .andEq("category", "XJG")
                    .andEq("is_create", 0)
                    .andEq("type", "VIDEO")
                    .selectList("id, file_url", TbyEducationView.class);
            for (TbyEducationView entity : dataList) {
                create(entity);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void createImgThumbnail(Long id) {
        if (id != null) {
            TbyEducationView view = get(id);
            createThumbnail(view);
            return;
        }
        try {
            List<TbyEducationView> dataList = db.table("tby_education_view v").whereTrue()
                    .andEq("is_create", 0)
                    .andEq("type", "IMAGE")
                    .selectList("id, file_url, file_suffix", TbyEducationView.class);
            for (TbyEducationView entity : dataList) {
                createThumbnail(entity);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void createThumbnail(TbyEducationView entity) {
        try {
            String sourceUrl = systemUrl + entity.getFileUrl();
            String outputPath1210x955 = tempUrl + entity.getId() + "1210x955." + entity.getFileSuffix();
            String outputPath235x162 = tempUrl + entity.getId() + "235x162." + entity.getFileSuffix();
            NetworkImageThumbnailGenerator.generateThumbnail(sourceUrl, outputPath1210x955, 1210, 955, 0.5f);
            NetworkImageThumbnailGenerator.generateThumbnail(sourceUrl, outputPath235x162, 235, 162, 0.5f);
            upload(entity.getId(), outputPath1210x955, 1210);
            upload(entity.getId(), outputPath235x162, 235);
            log.info("生成缩略图，id = " + entity.getId() + "，生成成功");
        } catch (Exception ex) {
            log.error("视图管理，图片生成缩略图异常：id = " + entity.getId(), ex);
        }
    }

    private void upload(Long id, String outputPath, int size) throws Exception {
        Gson gson = new Gson();
        String uploadResponse = HttpUtil.uploadFile(systemUrl + uploadUrl, outputPath);
        R<FileResult> r = gson.fromJson(uploadResponse, new TypeToken<R<FileResult>>(){}.getType());
        if (r.getCode() != 0) {
            log.error("视图管理，图片生成缩略图异常：id = " + id, r.getMsg());
            return;
        }
        if (StringUtils.isNotEmpty(r.getData().getFileName())) {
            TbyEducationView view = new TbyEducationView();
            view.setId(id);
            view.setIsCreate(1);
            if (size == 1210) {
                view.setThumbnailUrl("/file/img/" + r.getData().getFileName());
            } else if (size == 235) {
                view.setThumbnailIcon("/file/img/" + r.getData().getFileName());
            }
            tbyEducationViewRepo.updateById(view, true);
            File file = new File(outputPath);
            file.delete();
        }
    }

    private void create(TbyEducationView entity) {
        try {
            String videoUrl = "http://172.20.1.6:12007" + entity.getFileUrl();
            String outputPath = tempUrl + entity.getId() + ".jpg";
            // 调用方法截取视频第一帧
            URL u = new URL(videoUrl);
            InputStream is = u.openStream();
            boolean bool = VideoToImageUtil.videoToImage(is, outputPath);//FFmpegFrameGrabber.captureFirstFrameLinux(videoUrl, outputPath);
            System.out.println(videoUrl + ": " + bool);
            if (bool) {
                Gson gson = new Gson();
                String uploadResponse = HttpUtil.uploadFile(systemUrl + uploadUrl, outputPath);
                R<FileResult> r = gson.fromJson(uploadResponse, new TypeToken<R<FileResult>>(){}.getType());
                if (r.getCode() != 0) {
                    System.out.println("视图管理，宣教馆生成缩略图异常：id = " + entity.getId() + " " + r.getMsg());
                    return;
                }
                if (StringUtils.isNotEmpty(r.getData().getFileName())) {
                    TbyEducationView view = new TbyEducationView();
                    view.setId(entity.getId());
                    view.setIsCreate(1);
                    view.setThumbnailUrl("/file/img/" + r.getData().getFileName());
                    tbyEducationViewRepo.updateById(view, true);
                    System.out.println("主键id = " + entity.getId() + " 生成多略图地址为：" + r.getData().getFileName());
                    File file = new File(outputPath);
                    file.delete();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("视图管理，宣教馆生成缩略图异常：id = " + entity.getId(), e);
        }
    }
}
